package com.cooper.scraper;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.util.Map;
import java.util.Map.Entry;

import com.cooper.android.comm.FileUtils;
import com.cooper.android.comm.LRULinkedHashMap;
import com.cooper.android.comm.LRULinkedHashMap.RemoveEldestEntryListener;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.Log;

public class DownloadLRUCache implements RemoveEldestEntryListener<String, String> {
	
	private static final String BITMAP_CACHE_INFO_FILE_NAME = "bitmap_cache.ser";
	
	private static Map<String, String> pageBuffer;
	private static LRULinkedHashMap<String, String> bitmapBuffer;
	private DownloadParams params;

	
	public DownloadLRUCache(DownloadParams params){
		super();
		this.params = params;
		if (params.getPageBufferSize() > 0)
			pageBuffer = new LRULinkedHashMap<String, String>(params
					.getPageBufferSize());
		initBitmapBuffer();	
	}
	
	public String getPageFromCache(String key){
		return pageBuffer.get(key);
	}
	
	public void cachePage(String key,String page){
		pageBuffer.put(key, page);
	}
	
	public Bitmap getBitmapFromCache(String key) {
		if (bitmapBuffer != null) {
			String fileName = bitmapBuffer.get(key);
			String path = params.getBitmapCacheDir();
			File cacheFile = new File(path + "/" + fileName);
			if (cacheFile.exists()) {
				return BitmapFactory.decodeFile(cacheFile.getPath());
			} else {
				return null;
			}
		}
		return null;
	}
	
	public void cacheBitmap(String key, Bitmap bitmap) {
		if (bitmapBuffer != null) {
			String fileName = FileUtils.stringToFileName(key);
			String path = params.getBitmapCacheDir();
			File chcheFile = new File(path + "/" + fileName);
			if (chcheFile.exists()) {
				chcheFile.delete();
			}
			try {
				OutputStream out = new FileOutputStream(chcheFile);
				try {
					bitmap.compress(Bitmap.CompressFormat.JPEG, 85, out);
					bitmapBuffer.put(key, fileName);
				} finally {
					out.close();
				}
			} catch (IOException e) {
				Log.e("DownloadParams", e.getMessage(), e);
			}

		}
	}
	
	
	@SuppressWarnings("unchecked")
	private void initBitmapBuffer() {
		String cacheDirPath = params.getBitmapCacheDir();
		if (params.getBitmapBufferSize() > 0) {
			if (params.isSaveBitmapBufferToFile()) {
				try {
					FileInputStream istream = new FileInputStream(cacheDirPath
							+ "/" + BITMAP_CACHE_INFO_FILE_NAME);
					try {
						ObjectInputStream in = new ObjectInputStream(istream);
						int serMapSize = in.readInt();
						if (serMapSize == params.getBitmapBufferSize()) {
							bitmapBuffer = (LRULinkedHashMap<String, String>) in
									.readObject();
							Log.d("Downloader", "load cache frome file");
						}
					} finally {
						istream.close();
					}

				} catch (Exception e) {
					Log.w("Downloader", e.getMessage(), e);
				}
			}
			if (bitmapBuffer == null) {
				bitmapBuffer = new LRULinkedHashMap<String, String>(
						params.getBitmapBufferSize());
			}
			bitmapBuffer.setRemoveEldestEntryListener(this);
			//params.setBitmapBuffer(bitmapBuffer);

			File cacheDir = new File(cacheDirPath);
			if (cacheDir != null && cacheDir.exists())
				for (File cacheFile : cacheDir.listFiles()) {
					if (!cacheFile.equals(".")
							&& !cacheFile.equals("..")
							&& cacheFile.isFile()
							&& !bitmapBuffer.values().contains(
									cacheFile.getName())) {
						cacheFile.delete();
					}
				}
		} else {
			File cacheDir = new File(cacheDirPath);
			if (cacheDir != null && cacheDir.exists())
				for (File cacheFile : cacheDir.listFiles()) {
					if (!cacheFile.equals(".") && !cacheFile.equals("..")) {
						cacheFile.delete();
					}
				}
		}
	}
	
	public void shutDown(){
		if (bitmapBuffer != null && params.isSaveBitmapBufferToFile()) {
			bitmapBuffer.setRemoveEldestEntryListener(null);
			String cachePath = params.getBitmapCacheDir();
			for (Entry<String, String> cache : bitmapBuffer.entrySet()) {
				File cacheBitmapFile = new File(cachePath + "/"
						+ cache.getValue());
				if (!cacheBitmapFile.exists()) {
					bitmapBuffer.remove(cache.getKey());
				}
			}
			String serFilePath = cachePath + "/" + BITMAP_CACHE_INFO_FILE_NAME;
			File serFile = new File(serFilePath);
			if (serFile != null && serFile.exists()) {
				serFile.delete();
			}
			try {
				FileOutputStream outstream = new FileOutputStream(serFilePath);
				try {
					ObjectOutputStream out = new ObjectOutputStream(outstream);
					out.writeInt(params.getBitmapBufferSize());
					out.writeObject(bitmapBuffer);
					out.flush();
				} finally {
					outstream.close();
				}
			} catch (IOException e) {
				Log.e("Downloader", e.getMessage(), e);
			}
		} else {
			File cacheDir = new File(params.getBitmapCacheDir());
			if (cacheDir != null && cacheDir.exists())
				for (File cacheFile : cacheDir.listFiles()) {
					if (!cacheFile.equals(".") && !cacheFile.equals("..")
							&& cacheFile.isFile()) {
						cacheFile.delete();
					}
				}
		}
	}

	@Override
	public boolean onRemove(Entry<String, String> eldest) {
		File cacheFile = new File(params.getBitmapCacheDir() + "/"
				+ eldest.getValue());
		if (cacheFile.exists()) {
			cacheFile.delete();
		}
		return true;
	}

}
